package com.jetinno.hex;

import android.support.annotation.IntRange;

import java.math.BigInteger;

/**
 * Description:进制转换类
 * Author:mhwang
 * Date:2017/5/10
 * Version:V1.0
 */
public class HexTrans {
    /**
     * 等同{@link #hexString2Int}
     * 将字符串按16进制转为数字
     * 例如"F2"返回F2
     *
     * @param hexStr 长度不限制,但一般是 "00"~"FF"之间
     * @return 数字
     */
    public static int hexStr2Int(String hexStr) {
        BigInteger bigInteger = new BigInteger(hexStr, 16);
        return bigInteger.intValue();
    }

    /**
     * 等同{@link #hexStr2Int}
     * 将字符串按16进制转为数字
     * 例如"F2"返回F2
     *
     * @param hexStr 长度不限制,但一般是 "00"~"FF"之间
     * @return 数字
     */
    public static int hexString2Int(String hexStr) {
        try {
            return Integer.parseInt(hexStr, 16);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 将字符串按长度为2切割后再按16进制转为字节数组
     * 例如 "7FF2"按序返回[7F,F2]
     * 注意:这个转换有风险,因为后期如果byte转int时 0x00~0x7F是正数 0x80~0xFF是负数,而不是原本的真实值
     *
     * @param src 长度为2整数倍的字符串
     * @return 字节数组
     */
    public static byte[] hexString2Bytes(String src) {
        int len = src.length() / 2;
        byte[] ret = new byte[len];
        byte[] tmp = src.getBytes();
        for (int i = 0; i < len; i++) {
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return ret;
    }

    /**
     * 将字符串按长度为2切割后再按16进制转为字节数组
     * 例如 "7FF2"按序返回[7F,F2]
     *
     * @param src 长度为2整数倍的字符串
     * @return 字节数组
     */
    public static int[] hexString2Ints(String src) {
        int len = src.length() / 2;
        int[] ret = new int[len];
        for (int i = 0; i < len; i++) {
            String str = src.substring(i * 2, (i + 1) * 2);
            ret[i] = hexStr2Int(str);
        }
        return ret;
    }

    /**
     * 字节数组转换成16进制字符串显示
     * 例如[-0x80, 0x02, 0x02]按序返回 "800202"
     *
     * @param b      字节数组
     * @param length 截取字节数组的某一段的长度
     * @return 16进制字符串
     */
    public static String bytes2HexString(byte[] b, int length) {
        StringBuilder r = new StringBuilder();
        for (int i = 0; i < length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = "0" + hex;
            }
            r.append(hex.toUpperCase());
        }
        return r.toString();
    }

    /**
     * int转换成16进制字符串显示
     * 例如 128返回"80"
     *
     * @param i
     * @return
     */
    public static String int2HexString(int i) {
        String r = "";
        String hex = Integer.toHexString(i & 0xFF);
        if (hex.length() == 1) {
            hex = "0" + hex;
        }
        r += hex.toUpperCase();

        return r;
    }


    /**
     * 将字符串按长度为2切割后再按16进制转为数字后再转为8位长度的位数组的集合,再组装为字符串,以','相隔
     * 例如"F2F3"按序返回"11110010,11110011"
     *
     * @param hexValue 长度为2整数倍的字符串
     * @return 8位长度的bit数组相连接的字符串
     */
    public static String hexStrs2BitsText(String hexValue) {
        int hexLen = hexValue.length() / 2;
        final int byteLength = 8;
        if (hexLen == 0) {
            return null;
        }

        byte[] result = new byte[hexLen * byteLength];
        String[] hexs = new String[hexLen];
        int valueIndex = 0;
        // 获得字符串
        for (int i = 0; i < hexLen; i++) {
            hexs[i] = hexValue.substring(valueIndex, valueIndex + 2);
            valueIndex += 2;
        }

        StringBuilder builder = new StringBuilder();
        // 将每个字符串字节复制到结果数组
        for (String hex : hexs) {
            byte[] bytes = hexStrs2Bits(hex);
            if (bytes != null) {
                for (byte b : bytes) {
                    builder.append(b);
                }
                builder.append(",");
            }
        }
        int index = builder.lastIndexOf(",");
        if (index > 0) {
            builder.deleteCharAt(index);
        }
        return builder.toString();
    }

    /**
     * 将字符串按长度为2切割后再按16进制转为数字后再转为bit数组
     * 例如"F2F3"按序返回[1,1,1,1,0,0,1,0,1,1,1,1,0,0,1,1]
     *
     * @param hexValue 长度为2整数倍的字符串
     * @return 长度为8整数倍的bit数组
     */
    public static byte[] hexStrs2BitsArray(String hexValue) {
        int hexLen = hexValue.length() / 2;
        final int byteLength = 8;
        if (hexLen == 0) {
            return null;
        }

        byte[] result = new byte[hexLen * byteLength];
        String[] hexs = new String[hexLen];
        int valueIndex = 0;
        // 获得字符串
        for (int i = 0; i < hexLen; i++) {
            hexs[i] = hexValue.substring(valueIndex, valueIndex + 2);
            valueIndex += 2;
        }
        int resultIndex = 0;
        // 将每个字符串字节复制到结果数组
        for (String hex : hexs) {
            byte[] bytes = hexStrs2Bits(hex);
            if (bytes == null) {
                return null;
            }
            System.arraycopy(bytes, 0, result, resultIndex, byteLength);
            resultIndex += byteLength;
        }
        return result;
    }

    /**
     * 将长度为2的字符串按16进制转为数字后再转为8位长度的位数组
     * 例如"F2"按序返回[1,1,1,1,0,0,1,0]
     *
     * @param hexValue (长度为2的字符串，否则得不到值)
     * @return 返回长度为8的字节数组，每个值代表每一位的值
     */
    public static byte[] hexStrs2Bits(String hexValue) {
        if (hexValue.length() != 2) {
            return null;
        }
        byte bValue = (byte) Integer.parseInt(hexValue, 16);
        byte[] array = new byte[8];
        for (int i = 7; i >= 0; i--) {
            array[i] = (byte) (bValue & 1);
            bValue = (byte) (bValue >> 1);
        }
        return array;
    }

    /**
     * 将两个字节按高低位重新组合为新的字节
     * 例如 0x0F^0x02=0xF2
     *
     * @param src0 字节高位 范围0x00~0x0F
     * @param src1 字节低位 范围0x00~0x0F
     * @return 新的字节
     */
    private static byte uniteBytes(byte src0, byte src1) {
        byte _b0 = Byte.decode("0x" + new String(new byte[]{src0})).byteValue();
        _b0 = (byte) (_b0 << 4);
        byte _b1 = Byte.decode("0x" + new String(new byte[]{src1})).byteValue();
        byte ret = (byte) (_b0 ^ _b1);
        return ret;
    }

//    /**
//     * byte数组中取int数值，本方法适用于(低位在前，高位在后)的顺序。
//     *
//     * @param ary
//     *            byte数组
//     * @param offset
//     *            从数组的第offset位开始
//     * @return int数值
//     */
//    public static int bytesToInt(byte[] ary, int offset) {
//        int value;
//        value = (int) ((ary[offset]&0xFF)
//                | ((ary[offset+1]<<8) & 0xFF00)
//                | ((ary[offset+2]<<16)& 0xFF0000)
//                | ((ary[offset+3]<<24) & 0xFF000000));
//        return value;
//    }
//
//    /**
//     * byte数组中取int数值，本方法适用于(低位在后，高位在前)的顺序。和intToBytes2（）配套使用
//     */
//    public static int bytesToInt2(byte[] src, int offset) {
//        int value;
//        value = (int) ( ((src[offset] & 0xFF)<<24)
//                |((src[offset+1] & 0xFF)<<16)
//                |((src[offset+2] & 0xFF)<<8)
//                |(src[offset+3] & 0xFF));
//        return value;
//    }

    // 低位在前，高位在后
    public static byte[] int2bytesLFirst(int num) {
        byte[] result = new byte[4];
        result[3] = (byte) ((num >>> 24) & 0xff);
        result[2] = (byte) ((num >>> 16) & 0xff);
        result[1] = (byte) ((num >>> 8) & 0xff);
        result[0] = (byte) ((num >>> 0) & 0xff);
        return result;
    }

    // 高位在前，低位在后
    public static byte[] int2bytesHFirst(int num) {
        byte[] result = new byte[4];
        result[0] = (byte) ((num >>> 24) & 0xff);
        result[1] = (byte) ((num >>> 16) & 0xff);
        result[2] = (byte) ((num >>> 8) & 0xff);
        result[3] = (byte) ((num >>> 0) & 0xff);
        return result;
    }

    //高位在前，低位在后
    public static int bytes2intHFirst(byte[] bytes) {
        int result = 0;
        if (bytes.length == 4) {
            int a = (bytes[0] & 0xff) << 24;
            int b = (bytes[1] & 0xff) << 16;
            int c = (bytes[2] & 0xff) << 8;
            int d = (bytes[3] & 0xff);
            result = a | b | c | d;
        }
        return result;
    }

    //低位在前，高位在后
    public static int bytes2intLFirst(byte[] bytes) {
        int result = 0;
        if (bytes.length == 4) {
            int a = (bytes[3] & 0xff) << 24;
            int b = (bytes[2] & 0xff) << 16;
            int c = (bytes[1] & 0xff) << 8;
            int d = (bytes[0] & 0xff);
            result = a | b | c | d;
        }
        return result;
    }

    /**
     * 十六进制数据转换为十进制字符串数
     *
     * @param hex 例如 “13” 返回 “19”
     * @return
     */
    public static String hexToDec(String hex) {
        BigInteger data = new BigInteger(hex, 16);
        return data.toString(10);
    }

    /**
     * 获取一个字节的某一个'位'的值
     *
     * @param value         字节值 例如 0xF2 由低到高的8个bit值是 0100 1111 获取角标0的bit值就是0
     * @param childPosition '位'角标
     */
    public static int getChildBit(int value, @IntRange(from = 0, to = 7) int childPosition) {
        //value:F2
        //bytes:1111 0010
        byte[] bytes = hexStrs2Bits(String.format("%02X", value));
        //1个字节转为8个bit后,角标0是bit8,角标7是bit1,所以需要倒序,让角标0是bit1,角标7是bit8
        //bytes:0100 1111
        if (bytes != null && bytes.length > childPosition) {
            return bytes[7 - childPosition];
        }
        return 0;
    }
}
